﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace iNet.Media.Xmp
{
	/// <summary>
	/// XMP 中繼資料寫入元件。
	/// </summary>
	public class XmpWriter
	{
		#region 欄位
		
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 XmpWriter 執行個體。
		/// </summary>
		public XmpWriter()
		{ }
		#endregion
		#region Write
		/// <summary>
		/// 使用指定的 XML 寫入器寫入 XMP 中繼資料。
		/// </summary>
		/// <param name="writer">指定的 XML 寫入器。</param>
		/// <param name="properties">XMP Property 集合。</param>
		/// <exception cref="ArgumentNullException">writer 或 properties 為 Null (Visual Basic 為 Nothing)。</exception>
		public void Write(XmlTextWriter writer, IEnumerable<XmpProperty> properties)
		{
			//確認參數
			if (writer == null)
				throw new ArgumentNullException("writer");
			if (properties == null)
				throw new ArgumentNullException("properties");

			//將 XMP Property 分類
			Dictionary<XmpSchema, List<XmpProperty>> classifiedProperties = new Dictionary<XmpSchema, List<XmpProperty>>();
			foreach (XmpProperty property in properties)
			{
				XmpSchema schema = property.Name.Schema;
				if (schema != null)
				{
					List<XmpProperty> list;
					if (classifiedProperties.TryGetValue(schema, out list))
						list.Add(property);
					else
					{
						list = new List<XmpProperty>();
						list.Add(property);
						classifiedProperties[schema] = list;
					}
				}
			}

			//建立 XML 文件
			XmlDocument document = new XmlDocument();

			//建立根結點
			XmlNode rootNode = document.CreateElement("x", "xmpmeta", "adobe:ns:meta/");
			document.AppendChild(rootNode);

			//建立 rdf:RDF 節點
			XmlNode rdfNode = document.CreateElement("rdf", "RDF", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
			rootNode.AppendChild(rdfNode);

			//建立各分類的 XMP Property
			foreach (XmpSchema schema in classifiedProperties.Keys)
			{
				//建立 rdf:Description 節點
				XmlNode rdfDescriptionNode = document.CreateElement("rdf", "Description", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
				XmlAttribute nsAttr = document.CreateAttribute("xmlns:" + schema.NamespacePrefix);
				nsAttr.Value = schema.NamespaceURI;
				rdfDescriptionNode.Attributes.Append(nsAttr);
				rdfNode.AppendChild(rdfDescriptionNode);

				//建立 XMP Property 節點
				foreach (XmpProperty property in classifiedProperties[schema])
				{
					if (property.Value != null)
					{
						//建立名稱節點
						XmlNode propertyNode = document.CreateElement(schema.NamespacePrefix, property.Name.LocalName, schema.NamespaceURI);
						rdfDescriptionNode.AppendChild(propertyNode);

						//建立值節點
						property.Value.Serialize(propertyNode);
					}
				}
			}
			
			//初始化寫入器
			writer.Formatting = Formatting.Indented;

			//寫入 XMP Header
			writer.WriteProcessingInstruction("xpacket", "begin=\"\uFEFF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"");

			//寫入 XMP 文件
			document.Save(writer);

			//寫入 XMP Footer
			writer.WriteProcessingInstruction("xpacket", "end=\"w\"");
			writer.Flush();
		}
		/// <summary>
		/// 將指定的 XMP Property 集合寫入記憶體中。
		/// </summary>
		/// <param name="properties">XMP Property 集合。</param>
		/// <returns>表示已序列化的 XMP 文件。</returns>
		/// <exception cref="ArgumentNullException">properties 為 Null (Visual Basic 為 Nothing)。</exception>
		public byte[] Write(IEnumerable<XmpProperty> properties)
		{
			using (MemoryStream stream = new MemoryStream())
			{
				using (XmlTextWriter writer = new XmlTextWriter(stream, new UTF8Encoding(false)))
				{
					this.Write(writer, properties);
					return stream.ToArray();
				}
			}
		}
		#endregion
	}
}
